package evaluator

import (
	"fmt"

	"gitee.com/chuanjinge/go-interpreter-waiig/src/monkey/object"
)

// ---------------------- 内置函数 ------------------------

var lenFuncObj = &object.Builtin{Fn: BuiltinFuncLen}
var firstFuncObj = &object.Builtin{Fn: BuiltinFuncFirst}
var lastFuncObj = &object.Builtin{Fn: BuiltinFuncLast}
var putsFuncObj = &object.Builtin{Fn: BuiltinFuncPuts}

var builtinFunc = map[string]*object.Builtin{
	"len":   lenFuncObj,
	"first": firstFuncObj,
	"last":  lastFuncObj,
	"puts":  putsFuncObj,
}

// ---len 计算字符串长度或者数组长度
func BuiltinFuncLen(args ...object.Object) (object.Object, error) {
	if len(args) != 1 {
		// 可以根据实际情况处理参数数量错误，这里简单返回 nil
		return nil, fmt.Errorf("wrong number of arguments. got=%d, want=%d", len(args), 1)
	}

	var length int64
	switch args[0].Type() {
	case object.STRING_OBJ:
		obj := args[0].(*object.String)
		length = int64(len(obj.Value))
	case object.ARRAY_OBJ:
		obj := args[0].(*object.Array)
		length = int64(len(obj.Elements))
	default:
		return nil, fmt.Errorf("argument to `len` not supported, got %s", args[0].Type())
	}

	return &object.Integer{
		Value: length,
	}, nil
}

// --- first 获取数组的第一个元素
func BuiltinFuncFirst(args ...object.Object) (object.Object, error) {
	if len(args) != 1 {
		// 可以根据实际情况处理参数数量错误，这里简单返回 nil
		return nil, fmt.Errorf("wrong number of arguments. got=%d, want=%d", len(args), 1)
	}

	switch args[0].Type() {
	case object.ARRAY_OBJ:
		obj := args[0].(*object.Array)
		if len(obj.Elements) == 0 {
			return NULL, nil
		}
		// 将 obj.Elements 取出第一个，保留剩余的
		item := obj.Elements[0]
		obj.Elements = obj.Elements[1:]
		return item, nil
	default:
		return nil, fmt.Errorf("argument to `first` not supported, got %s", args[0].Type())
	}
}

// --- last 获取数组的最后一个元素
func BuiltinFuncLast(args ...object.Object) (object.Object, error) {
	if len(args) != 1 {
		// 可以根据实际情况处理参数数量错误，这里简单返回 nil
		return nil, fmt.Errorf("wrong number of arguments. got=%d, want=%d", len(args), 1)
	}

	switch args[0].Type() {
	case object.ARRAY_OBJ:
		obj := args[0].(*object.Array)
		if len(obj.Elements) == 0 {
			return NULL, nil
		}
		idxLast := len(obj.Elements) - 1
		item := obj.Elements[idxLast]
		if idxLast == 0 {
			obj.Elements = []object.Object{}
		} else {
			obj.Elements = obj.Elements[0 : idxLast-1]
		}
		return item, nil
	default:
		return nil, fmt.Errorf("argument to `first` not supported, got %s", args[0].Type())
	}
}

// 输出要打印的对象到控制台
func BuiltinFuncPuts(args ...object.Object) (object.Object, error) {
	for _, arg := range args {
		fmt.Println(arg.Inspect())
	}

	return NULL, nil
}
